{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "119af92c-f02c-4729-84ac-0f69d6208c1b",
   "metadata": {},
   "source": [
    "# Sequential\n",
    "\n",
    "本文将展示Langchain结合qianfan使用`Sequential` 以及 `LCEL` 进行大模型应用Prompt和Chain的组装调用，原文请参考[Langchain Seuqential](https://python.langchain.com/docs/expression_language/)\n",
    "总的来说Langchain更推荐是`LCEL`的方式进行实现"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6bf0d09c",
   "metadata": {},
   "outputs": [],
   "source": [
    "#-# cell_skip\n",
    "! pip install \"qianfan>=0.2.2\" -U\n",
    "! pip install langchain "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e4f32134",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "# qianfan sdk 鉴权\n",
    "os.environ[\"QIANFAN_AK\"] = \"your_ak\"\n",
    "os.environ[\"QIANFAN_SK\"] = \"your_sk\""
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "3e363e64",
   "metadata": {},
   "source": [
    "首先定义两段prompt， 第一段Prompt主要指令为给出一个标题得到一份电影的主干，第二段为电影主干生成一篇评论"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "443e62b9-8a68-468e-b91d-f19de2993fe8",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.prompts import PromptTemplate\n",
    "\n",
    "synopsis_prompt = PromptTemplate.from_template(\"\"\"你是一位编剧。鉴于电影的标题，你的任务是为该标题撰写一个电影剧情的主干。\n",
    "\n",
    "标题：{title}\n",
    "编剧：以下是上述电影的主干：\"\"\"\n",
    ")\n",
    "\n",
    "review_template =  \"\"\"你是《豆瓣影评》的深度用户。鉴于该电影的故事主干，你的任务是为该电影撰写一篇宣传称赞的评论。\n",
    "\n",
    "主干：\n",
    "{synopsis}\n",
    "《豆瓣影评》戏剧评论家对上述戏剧的评论：:\"\"\"\n",
    "\n",
    "review_prompt = PromptTemplate.from_template(review_template)\n",
    "\n",
    "title=\"众里寻他千百度\""
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "7d1b284f-73b4-4f3c-ab88-e4c6f4b0bf76",
   "metadata": {},
   "source": [
    "## LCEL(推荐)\n",
    "\n",
    "LCEL（LangChain Expression Language ）是Langchain对于组装多个Chain的一种语法设计，通过LCEL可以快速简单的串联一个多个变量，PromptTemplate和Chain的组合Pipeline，底层通过实现在Runnable中的__or__()实现该语法，\n",
    "对于Langchain中的Prompt，LLM，Chain，Parser等各种组件来说，都派生自Runnable，所以可以通过以下的语法进行串联，以实现多个LLM+prompt的链式调用"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "c0a43154-7624-41b7-9832-f2022af41fba",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'《众里寻他千百度》是一部令人惊喜的电影，它成功地呈现了一个富有奇幻色彩的故事，同时也展现出深厚的人性。这部电影以一种巧妙的方式开始，通过主人公小杰在网络上寻找兼职的过程中无意中被传送到了一个古代奇幻世界的主线，巧妙地串联起整个故事。\\n\\n在探索这个世界的过程中，小杰不仅遇到了各种人物和挑战，还逐渐发现这个世界与他所寻找的答案有关。他需要解开这个世界中的谜团，才能找到回家的路。这个过程不仅考验了他的智慧和勇气，也让他面对自己内心的挣扎和成长。这种深度的人性探索使得电影具有了更广泛的主题和观众吸引力。\\n\\n电影中的角色塑造也非常出色。小杰这个主角既有现代人的聪明和敏感，又有古代人的勇敢和坚定。他的感情发展与他对回家的渴望相交织，使他成为了一个令人难忘的角色。同时，小杰和他的伙伴们共同面对困难和挑战的经历，也使电影充满了合作与友谊的主题。\\n\\n此外，电影的视觉效果和音乐也堪称一流。它利用了奇幻元素创造了一个神秘而美丽的世界，同时配乐也恰到好处地营造出了一种神秘而引人入胜的氛围。这些视觉和听觉元素共同为观众创造了一个引人入胜的观影体验。\\n\\n总的来说，《众里寻他千百度》是一部富有创意和深度的电影。它不仅成功地呈现了一个奇幻世界的故事，也深入探讨了人性的主题。我强烈推荐这部电影给所有喜欢奇幻、冒险和深度故事的电影爱好者。这部电影无疑会成为今年的一部佳作，我期待看到更多观众被它所吸引并沉浸在其中。'"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain.chat_models import QianfanChatEndpoint \n",
    "from langchain.schema import StrOutputParser\n",
    "\n",
    "llm = QianfanChatEndpoint()\n",
    "chain = (\n",
    "    {\"synopsis\": synopsis_prompt | llm | StrOutputParser()}\n",
    "    | review_prompt\n",
    "    | llm\n",
    "    | StrOutputParser()\n",
    ")\n",
    "chain.invoke({\"title\": title})"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "c37f72d5-a005-444b-b97e-39df86c515c7",
   "metadata": {},
   "source": [
    "通过`RunnablePassthrough.assign`我们可以将将之前的输入字段进行透传，并分配我们本次的输出和字段名"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "9f9fb8ad-b6eb-49c3-a1d1-83f4460525e6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'synopsis': '电影《众里寻他千百度》的主干：\\n\\n故事发生在一个现代都市，讲述了一群年轻人在寻找自我和真爱的过程中，经历了种种挫折和成长的故事。\\n\\n故事的主角是一个名叫小杨的年轻人，他是一个性格内向、不善言辞的人，一直生活在自己的世界里。他有一个梦想，就是找到一个能够理解他、与他心灵相通的人。然而，在现实生活中，他很难找到这样的人，因此他决定通过互联网寻找他的另一半。\\n\\n小杨在网络上结识了一群志同道合的朋友，他们都是寻找真爱的年轻人。这群人在一起分享彼此的经历和感受，互相鼓励和支持。在这个过程中，小杨逐渐变得更加自信和勇敢，也开始尝试一些以前从未做过的事情，比如参加社交活动、改变自己的形象等等。\\n\\n然而，寻找真爱的过程并不总是一帆风顺。小杨和他的朋友们遇到了许多挫折和困难，比如被人误解、被人拒绝、甚至是网络诈骗等等。他们中的一些人在经历了这些挫折之后，选择了放弃寻找真爱，但小杨却并没有放弃。他坚信只有不断尝试和努力，才能找到真正的爱情。\\n\\n最后，小杨在一次偶然的机会下，遇到了一个和他有着相似经历的女孩小雨。他们在一场社交活动中相识，并且逐渐发现了彼此的共同点。小雨是一个善良、温柔、理解小杨的人，她让小杨感受到了真正的爱情和温暖。最终，他们走到了一起，并一起面对未来的挑战和机遇。\\n\\n这个故事的主干围绕着寻找真爱的主题展开，通过一群年轻人的经历和成长，展现了现代都市中年轻人面对爱情的态度和选择。同时，也表达了坚持和勇敢面对困难的重要性。电影的结尾温馨感人，让人感受到了爱情的力量和美好。',\n",
       " 'custom_review_field': '《众里寻他千百度》是一部充满情感和感人的电影，它通过一群年轻人在寻找真爱的过程中所经历的种种挫折和成长，展现了现代都市中年轻人面对爱情的态度和选择。电影的主干清晰明了，故事情节紧凑，人物形象鲜明，情感表达真挚，让人深受感动。\\n\\n首先，电影中的主角小杨是一个内向、不善言辞的人，他一直生活在自己的世界里，寻找着真正的爱情。他的经历和成长过程非常真实，让人感到非常亲切。他的朋友们也是一群寻找真爱的年轻人，他们在一起分享彼此的经历和感受，互相鼓励和支持。这些人物形象都非常生动，让人感到非常真实和亲切。\\n\\n其次，电影中的情节非常感人。小杨和他的朋友们遇到了许多挫折和困难，比如被人误解、被人拒绝、甚至是网络诈骗等等。但是，他们并没有放弃寻找真爱，而是坚持着不断尝试和努力。这种坚持和勇敢面对困难的精神是非常值得我们学习的。\\n\\n最后，电影的结尾温馨感人，让人感受到了爱情的力量和美好。小杨和小雨在一场社交活动中相识，并逐渐发现了彼此的共同点。他们走到了一起，并一起面对未来的挑战和机遇。这种爱情的美好让人感到非常温暖和感动。\\n\\n总之，《众里寻他千百度》是一部非常值得观看的电影。它通过一群年轻人在寻找真爱的过程中所经历的种种挫折和成长，展现了现代都市中年轻人面对爱情的态度和选择，同时传达了坚持和勇敢面对困难的重要性。它的结尾温馨感人，让人感受到了爱情的力量和美好。我强烈推荐这部电影给所有喜欢情感电影的观众。'}"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain.schema.runnable import RunnablePassthrough\n",
    "\n",
    "synopsis_chain = synopsis_prompt | llm | StrOutputParser()\n",
    "review_chain = review_prompt | llm | StrOutputParser()\n",
    "chain = {\"synopsis\": synopsis_chain} | RunnablePassthrough.assign(custom_review_field=review_chain)\n",
    "chain.invoke({\"title\": title})"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "9af35228-d3ff-4c95-8168-506c72618ace",
   "metadata": {},
   "source": [
    "## SequentialChain\n",
    "\n",
    "顺序链允许您连接多个链并将它们组合成执行某个特定场景的管道。有两种类型的顺序链：\n",
    "\n",
    "- SimpleSequentialChain：最简单的SequentialChain形式，其中每个步骤都具有单一的输入/输出，一个步骤的输出是下一个步骤的输入。\n",
    "- SequentialChain：更通用的SequentialChain形式，允许多个输入/输出。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6c25c84e-c9f6-43be-8282-78fbd1525091",
   "metadata": {},
   "source": [
    "### SimpleSequentialChain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "7ed84b1a-66a6-463c-ba61-1e98434e1958",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.chains import LLMChain\n",
    "from langchain.chat_models import QianfanChatEndpoint \n",
    "from langchain.prompts import PromptTemplate\n",
    "\n",
    "# This is an LLMChain to write a synopsis given a title of a play.\n",
    "llm = QianfanChatEndpoint(model=\"ERNIE-Bot\", temperature=0.5)\n",
    "synopsis_chain = LLMChain(llm=llm, prompt=synopsis_prompt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "a3173022-e2c7-478b-a9b8-4a535d905a1c",
   "metadata": {},
   "outputs": [],
   "source": [
    "review_chain = LLMChain(llm=llm, prompt=review_prompt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "b2fdd3d9-cd49-4606-b016-678e27d2b6e0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001B[1m> Entering new SimpleSequentialChain chain...\u001B[0m\n",
      "\u001B[36;1m\u001B[1;3m故事开始于一个繁华的城市，主人公李翔（男，30岁，职业：自由作家）坐在咖啡厅的角落，手中紧握着一封破旧的信。这封信引领他来到这个城市，寻找一个失散多年的女子——苏梦（女，28岁，职业：舞蹈教师）。\n",
      "\n",
      "李翔与苏梦相识于十年前的一个夏天。当时，他们都在海边的小镇上度假。苏梦的美丽与才华给李翔留下了深刻的印象，他们度过了一个美好的夏天。然而，分别后他们失去了联系。这封信是李翔在整理旧物时发现的，信是苏梦写给他的，信中提到他们在那个夏天曾共同许下的诺言。\n",
      "\n",
      "李翔决定寻找苏梦，他开始在城市的各个角落寻找她的踪迹。在这个过程中，他遇到了许多人和事，也影响了他对生活的看法。他发现，除了苏梦，他还有许多其他值得珍惜的人和事。\n",
      "\n",
      "在寻找的过程中，李翔遇到了一个叫做林悦（女，25岁，职业：酒吧歌手）的女孩。林悦对生活充满热情，她鼓励李翔继续寻找苏梦，同时也启发了他去追寻自己的梦想。在林悦的陪伴下，李翔开始了一段充满挑战和希望的旅程。\n",
      "\n",
      "经过一系列的挫折和困难，李翔终于找到了苏梦。然而，他发现苏梦已经有了自己的生活和家庭。李翔深感失落，但同时也明白了他在这段时间里所得到的成长和启示。他意识到，生命中有很多值得追求的东西，而这些东西并不一定要在一个人身上找到。\n",
      "\n",
      "最后，李翔决定和林悦一起继续追求他们的梦想。他们在这个城市里开创了自己的事业，并且帮助了许多像他们一样有梦想的年轻人。他们的故事激励了更多的人去追求自己的梦想和生活价值。\n",
      "\n",
      "电影以李翔和林悦在城市中的奋斗和成长为主线，展现了现代人在追求梦想和生活价值的过程中所经历的挫折、成长和启示。同时，电影也表达了珍惜身边的人和事，勇敢面对生活的态度。\u001B[0m\n",
      "\u001B[33;1m\u001B[1;3m《寻找苏梦》是一部感人至深的现代爱情故事，同时也是一部充满启示和鼓励的人生旅程。影片以李翔的寻找为主线，展现了一个男人在追寻自己内心深处的梦想和感情的过程中所经历的挫折、成长和启示。\n",
      "\n",
      "影片的情节紧凑，人物形象鲜明。每个角色都有自己的故事和价值，他们的经历和感情相互交织，形成了一幅丰富多彩的人生画卷。特别是李翔和苏梦之间的感情纠葛，以及他们在寻找过程中所经历的种种挫折和磨难，让人不禁为之动容。\n",
      "\n",
      "影片的拍摄手法也非常出色，导演通过运用独特的视角和拍摄技巧，将现代城市的繁华与人们内心的情感世界完美地结合在一起。每一个镜头都充满了情感和力量，让人对生活的美好有了更深刻的认识。\n",
      "\n",
      "此外，影片还充满了许多细腻的情感元素。例如，李翔与林悦之间的友谊和相互扶持，以及他们在追求梦想的过程中所经历的成长和变化，都让人感受到了生活的美好和温暖。这些细腻的情感元素不仅让人对故事产生了共鸣，也让人对生活有了更深刻的认识和理解。\n",
      "\n",
      "总的来说，《寻找苏梦》是一部充满情感和启示的电影。它不仅展现了一个男人在追寻自己内心深处的梦想和感情的过程中所经历的挫折、成长和启示，更是一部充满力量和温暖的电影。它鼓励人们勇敢面对生活中的挑战和困难，同时也提醒人们珍惜身边的人和事，去追求自己的梦想和生活价值。对于喜欢浪漫爱情故事的观众来说，《寻找苏梦》绝对是一部不容错过的佳作。\u001B[0m\n",
      "\n",
      "\u001B[1m> Finished chain.\u001B[0m\n"
     ]
    }
   ],
   "source": [
    "# This is the overall chain where we run these two chains in sequence.\n",
    "from langchain.chains import SimpleSequentialChain\n",
    "\n",
    "overall_chain = SimpleSequentialChain(\n",
    "    chains=[synopsis_chain, review_chain], verbose=True\n",
    ")\n",
    "\n",
    "review = overall_chain.run(title)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "5f023a0c-9305-4a14-ae24-23fff9933861",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "《寻找苏梦》是一部感人至深的现代爱情故事，同时也是一部充满启示和鼓励的人生旅程。影片以李翔的寻找为主线，展现了一个男人在追寻自己内心深处的梦想和感情的过程中所经历的挫折、成长和启示。\n",
      "\n",
      "影片的情节紧凑，人物形象鲜明。每个角色都有自己的故事和价值，他们的经历和感情相互交织，形成了一幅丰富多彩的人生画卷。特别是李翔和苏梦之间的感情纠葛，以及他们在寻找过程中所经历的种种挫折和磨难，让人不禁为之动容。\n",
      "\n",
      "影片的拍摄手法也非常出色，导演通过运用独特的视角和拍摄技巧，将现代城市的繁华与人们内心的情感世界完美地结合在一起。每一个镜头都充满了情感和力量，让人对生活的美好有了更深刻的认识。\n",
      "\n",
      "此外，影片还充满了许多细腻的情感元素。例如，李翔与林悦之间的友谊和相互扶持，以及他们在追求梦想的过程中所经历的成长和变化，都让人感受到了生活的美好和温暖。这些细腻的情感元素不仅让人对故事产生了共鸣，也让人对生活有了更深刻的认识和理解。\n",
      "\n",
      "总的来说，《寻找苏梦》是一部充满情感和启示的电影。它不仅展现了一个男人在追寻自己内心深处的梦想和感情的过程中所经历的挫折、成长和启示，更是一部充满力量和温暖的电影。它鼓励人们勇敢面对生活中的挑战和困难，同时也提醒人们珍惜身边的人和事，去追求自己的梦想和生活价值。对于喜欢浪漫爱情故事的观众来说，《寻找苏梦》绝对是一部不容错过的佳作。\n"
     ]
    }
   ],
   "source": [
    "print(review)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "d09df151-6a66-4982-8424-44ec3c92422d",
   "metadata": {},
   "source": [
    "### SequentialChain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "7481ed64-22f3-47dc-9796-c372eeb4f7bd",
   "metadata": {},
   "outputs": [],
   "source": [
    "# This is an LLMChain to write a synopsis given a title of a play and the era it is set in.\n",
    "synopsis_template = \"\"\"\"你是一位编剧。鉴于电影的标题和背景，你的任务是为该标题撰写一个电影剧情的主干。\n",
    "\n",
    "Title: {title}\n",
    "Era: {era}\n",
    "Playwright: This is a synopsis for the above play:\"\"\"\n",
    "synopsis_prompt_template = PromptTemplate(\n",
    "    input_variables=[\"title\", \"era\"], template=synopsis_template\n",
    ")\n",
    "synopsis_chain = LLMChain(\n",
    "    llm=llm, prompt=synopsis_prompt_template, output_key=\"synopsis\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "6d5ec9be-7101-460a-9fc1-7ef2d02434e7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001B[1m> Entering new SequentialChain chain...\u001B[0m\n",
      "\n",
      "\u001B[1m> Finished chain.\u001B[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'title': '众里寻他千百度',\n",
       " 'era': '21世纪20年代的广东深圳',\n",
       " 'synopsis': '标题：众里寻他千百度\\n\\n21世纪20年代的广东深圳，一个繁华而充满活力的城市。李明，一个才华横溢的年轻人，为了实现自己的梦想，离开故乡来到深圳寻求发展。他渴望成为一名成功的企业家，以改变自己和家人的命运。\\n\\n在深圳的繁华都市中，李明结识了许多志同道合的朋友，他们一起为了梦想努力奋斗。然而，在追逐梦想的道路上，李明渐渐发现，现实往往比想象中更加残酷。\\n\\n一次偶然的机会，李明结识了一位神秘女子林燕。林燕拥有着与众不同的气质和优雅的举止，让李明为之倾心。然而，林燕似乎隐藏着一些不为人知的秘密。\\n\\n在林燕的引导下，李明开始了一段充满挑战和奇遇的冒险之旅。他逐渐发现，自己正置身于一个巨大的阴谋之中，而林燕则是他揭开真相的关键人物。\\n\\n在这场冒险中，李明不断地挑战自己的极限，成长为一个更加成熟、坚强的人。而林燕也逐渐展现出她真实的身份和目的，让李明深感震撼。\\n\\n最终，在一场惊心动魄的决战中，李明成功揭开了阴谋的真相，并实现了自己的梦想。而他与林燕之间的感情也经历了重重考验，最终修成正果。\\n\\n在这个充满挑战和奇遇的冒险之旅中，李明不断地寻找自己内心的力量和勇气，最终实现了自己的梦想。而这段旅程也让他的生命变得更加丰富多彩，让他明白了生命的真谛。',\n",
       " 'review': '这部电影的故事主干充满了吸引力和张力，让人仿佛置身于一个充满挑战和奇遇的冒险之旅中。李明的成长和他与林燕之间的感情发展都让人深感震撼和感动。\\n\\n首先，电影的背景设定在21世纪20年代的广东深圳，一个繁华而充满活力的城市。这个背景为电影提供了一个非常具有现实感的舞台，让观众能够更好地理解和感受到李明在追逐梦想的过程中所面临的挑战和困难。\\n\\n其次，电影中的人物形象塑造非常成功。李明是一个充满活力和梦想的年轻人，他的决心和勇气让人感到敬佩。而林燕则是一个充满神秘和魅力的女性，她的出现让整个故事变得更加有趣和引人入胜。\\n\\n此外，电影的剧情设计也非常巧妙。在李明追求梦想的过程中，他不仅面临着来自外界的竞争和压力，还要面对自己内心的挣扎和矛盾。这些情节的设计让观众更加深入地了解了李明的内心世界和他的成长历程。\\n\\n最后，电影的制作质量也非常出色。无论是画面、音效还是配乐都非常出色，让观众能够更好地沉浸在故事中。\\n\\n总之，这部电影的故事主干充满了吸引力和张力，让观众能够更好地理解和感受到主人公的成长历程和情感发展。同时，电影的制作质量也非常出色，让观众能够更好地沉浸在故事中。'}"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# This is an LLMChain to write a review of a play given a synopsis.\n",
    "# template = \"\"\"You are a play critic from the New York Times. Given the synopsis of play, it is your job to write a review for that play.\n",
    "\n",
    "# Play Synopsis:\n",
    "# {synopsis}\n",
    "# Review from a New York Times play critic of the above play:\"\"\"\n",
    "prompt_template = PromptTemplate(input_variables=[\"synopsis\"], template=review_template)\n",
    "review_chain = LLMChain(llm=llm, prompt=prompt_template, output_key=\"review\")\n",
    "\n",
    "era = \"21世纪20年代的广东深圳\"\n",
    "# This is the overall chain where we run these two chains in sequence.\n",
    "from langchain.chains import SequentialChain\n",
    "\n",
    "overall_chain = SequentialChain(\n",
    "    chains=[synopsis_chain, review_chain],\n",
    "    input_variables=[\"era\", \"title\"],\n",
    "    # Here we return multiple variables\n",
    "    output_variables=[\"synopsis\", \"review\"],\n",
    "    verbose=True,\n",
    ")\n",
    "\n",
    "\n",
    "overall_chain({\"title\": title, \"era\": era})"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "6f009360",
   "metadata": {},
   "source": [
    "### 使用Memory管理复杂的上下文\n",
    "\n",
    "对于复杂场景下需要使用Memory管理上下文，Sequential可以实现更复杂的逻辑，以下例子包含了多步LLMChain的调用，同时存在前后输入输出依赖，并使用Memory管理了整个调用链上保持不变的变量例如`title`,`location`等"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "e50d0da6-dea1-428f-94eb-c7dfc3d298e3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001B[1m> Entering new SequentialChain chain...\u001B[0m\n",
      "\n",
      "\u001B[1m> Finished chain.\u001B[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'title': '众里寻他千百度',\n",
       " 'era': '21世纪20年代的广东深圳',\n",
       " 'time': '12月初冬，早7点',\n",
       " 'location': '南山后海深圳湾公园',\n",
       " 'social_post_text': '【电影推荐】《众里寻他千百度》—— 在深圳的早冬，感受爱与被爱的温度\\n\\n亲爱的朋友们，今天想给大家推荐一部充满情感与内涵的电影——《众里寻他千百度》。这部电影以21世纪20年代的广东深圳为背景，讲述了一段关于爱情、友情和人生价值的长篇画卷。\\n\\n故事的主角林小雨，是一个年轻有为的程序员，被指派开发一款名为\"众里寻他千百度\"的交友软件。这款软件运用了最先进的人工智能技术，旨在帮助用户在茫茫人海中寻找自己的另一半。然而，在全身心投入工作的同时，林小雨忽视了女友小月的感受。小月为了引起林小雨的注意，偷偷将交友软件中的异性匹配功能修改为同性匹配。当林小雨发现这个秘密时，他为了找出真相，尝试使用这款软件寻找答案。\\n\\n在这个寻找答案的过程中，林小雨遇到了形形色色的人，其中包括一位热情洋溢的同性恋者、一位寻找真爱的富家女、一位善良温暖的咖啡店老板娘等。他们都在使用\"众里寻他千百度\"这款软件，寻找自己的爱情和幸福。通过与这些人的交流，林小雨开始反思自己的生活和爱情。他渐渐明白，爱情不是一场游戏，而是一种责任和承诺。他决定放弃开发这款软件，转而投身公益事业，帮助那些需要帮助的人找到自己的幸福。\\n\\n在这个过程中，林小雨和小月重新找回了彼此的感情。他们一起参与公益事业，将爱传递给更多的人。最终，他们成为了一对幸福的恋人，过上了简单而美好的生活。虽然\"众里寻他千百度\"这款交友软件未能问世，但它却帮助了林小雨找到了自己的人生方向和爱情的真谛。\\n\\n这部电影的故事主干富有深度和内涵，展现了一段关于爱情、友情和人生价值的长篇画卷。影片以21世纪20年代的广东深圳为背景，描绘了现代都市中人们的生活状态和情感纠葛。林小雨这个角色塑造得十分立体。他是一个充满活力和创造力的程序员，但在忙碌的工作中却忽视了女友小月的感受。影片通过这个情节，深入探讨了现代都市中普遍存在的情感问题，即工作和生活的平衡。影片中的另一条主线是林小雨开发的交友软件\"众里寻他千百度\"。这个软件不仅具有先进的人工智能技术，还蕴含了人类对爱情和幸福的渴望。影片通过这个软件，展现了现代人在茫茫人海中寻找另一半的艰辛和期待。影片中的角色塑造也十分出色。小月、同性恋者、富家女、咖啡店老板娘等人物形象各具特色，他们的经历和感情线也使得影片更加丰富多彩。影片的结尾也十分感人。林小雨最终放弃了开发交友软件，投身公益事业帮助那些需要帮助的人找到幸福。这个情节不仅传递了正能量也表达了人类对美好生活的向往和追求。\\n\\n总的来说，《众里寻他千百度》这部电影是一部充满情感和内涵的作品它深刻地探讨了现代都市中人类的情感和生活状态同时也传递了人类对美好生活的向往和追求这部电影值得每一个观众深思和感悟。在这个冬天的早晨让我们一起走进电影院感受这部电影带来的温暖与感动吧！'}"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain.chains import SequentialChain\n",
    "from langchain.memory import SimpleMemory\n",
    "\n",
    "template = \"\"\"你是一家电影公司的社交媒体经理。鉴于电影的标题、设定的时代、日期、时间和地点，以及电影的主干和评论，你的任务是为该电影撰写一则社交媒体帖子。\n",
    "\n",
    "以下是关于电影的时间和地点的一些背景信息：:\n",
    "时间: {time}\n",
    "地点: {location}\n",
    "\n",
    "电影主干:\n",
    "{synopsis}\n",
    "电影评论：\n",
    "{review}\n",
    "\n",
    "社交媒体帖子:\n",
    "\"\"\"\n",
    "\n",
    "time = \"12月初冬，早7点\"\n",
    "location = \"南山后海深圳湾公园\"\n",
    "prompt_template = PromptTemplate(\n",
    "    input_variables=[\"synopsis\", \"review\", \"time\", \"location\"], template=template\n",
    ")\n",
    "social_chain = LLMChain(llm=llm, prompt=prompt_template, output_key=\"social_post_text\")\n",
    "\n",
    "overall_chain = SequentialChain(\n",
    "    memory=SimpleMemory(\n",
    "        memories={\"time\": time, \"location\": location}\n",
    "    ),\n",
    "    chains=[synopsis_chain, review_chain, social_chain],\n",
    "    input_variables=[\"era\", \"title\"],\n",
    "    # Here we return multiple variables\n",
    "    output_variables=[\"social_post_text\"],\n",
    "    verbose=True,\n",
    ")\n",
    "\n",
    "overall_chain({\"title\": title, \"era\": era})"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "base",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.5"
  },
  "vscode": {
   "interpreter": {
    "hash": "58f7cb64c3a06383b7f18d2a11305edccbad427293a2b4afa7abe8bfc810d4bb"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
